home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / BNU22SR1.ZIP / src / binutils.2 / bfd / coff-a29.c < prev    next >
C/C++ Source or Header  |  1993-05-30  |  10KB  |  341 lines

  1. /* BFD back-end for AMD 29000 COFF binaries.
  2.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  3.    Contributed by David Wood at New York University 7/8/91.
  4.  
  5. This file is part of BFD, the Binary File Descriptor library.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #define A29K 1
  22.  
  23. #include "bfd.h"
  24. #include "sysdep.h"
  25. #include "libbfd.h"
  26. #include "obstack.h"
  27. #include "coff/a29k.h"
  28. #include "coff/internal.h"
  29. #include "libcoff.h"
  30.  
  31. #define INSERT_HWORD(WORD,HWORD)    \
  32.     (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
  33. #define EXTRACT_HWORD(WORD) \
  34.     (((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff)
  35. #define SIGN_EXTEND_HWORD(HWORD) \
  36.     ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD))
  37.  
  38. /* Provided the symbol, returns the value reffed */
  39. static  long
  40. get_symbol_value(symbol)       
  41. asymbol *symbol;
  42. {                                             
  43.   long relocation = 0;
  44.  
  45.   if (bfd_is_com_section (symbol->section))
  46.   {
  47.     relocation = 0;                           
  48.   }
  49.   else 
  50.   {                                      
  51.     relocation = symbol->value +
  52.      symbol->section->output_section->vma +
  53.       symbol->section->output_offset;
  54.   }                                           
  55.  
  56.   return(relocation);
  57. }
  58.  
  59. /* this function is in charge of performing all the 29k relocations */
  60.  
  61. static bfd_reloc_status_type
  62. DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section, output_bfd),
  63.       bfd *abfd AND
  64.       arelent *reloc_entry AND
  65.       asymbol *symbol_in AND
  66.       PTR data AND
  67.       asection *input_section AND
  68.       bfd *output_bfd)
  69. {
  70.   /* the consth relocation comes in two parts, we have to remember
  71.      the state between calls, in these variables */
  72.   static boolean part1_consth_active = false;
  73.   static unsigned long part1_consth_value;
  74.  
  75.   unsigned long insn;
  76.   unsigned long sym_value;
  77.   unsigned long unsigned_value;
  78.   unsigned short r_type;
  79.   long signed_value;
  80.  
  81.   unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
  82.   bfd_byte  *hit_data =addr + (bfd_byte *)(data);
  83.     
  84.   r_type = reloc_entry->howto->type;
  85.  
  86.   if (output_bfd) {
  87.     /* Partial linking - do nothing */
  88.     reloc_entry->address += input_section->output_offset;
  89.     return bfd_reloc_ok;
  90.  
  91.   }
  92.  
  93.   if (symbol_in && (symbol_in->section == &bfd_und_section))
  94.   {
  95.     /* Keep the state machine happy in case we're called again */
  96.     if (r_type == R_IHIHALF) 
  97.     {
  98.       part1_consth_active = true;
  99.       part1_consth_value  = 0;
  100.     }
  101.     return(bfd_reloc_undefined);
  102.   }
  103.  
  104.   if ((part1_consth_active) && (r_type != R_IHCONST)) 
  105.   {
  106.     fprintf(stderr,"Relocation problem : ");
  107.     fprintf(stderr,"Missing IHCONST in module %s\n",abfd->filename);
  108.     part1_consth_active = false;
  109.     return(bfd_reloc_dangerous);
  110.   }
  111.  
  112.  
  113.   sym_value = get_symbol_value(symbol_in);
  114.  
  115.   switch (r_type) 
  116.   {
  117.    case R_IREL:     
  118.     insn = bfd_get_32(abfd, hit_data); 
  119.     /* Take the value in the field and sign extend it */
  120.     signed_value = EXTRACT_HWORD(insn) << 2;
  121.     signed_value = SIGN_EXTEND_HWORD(signed_value);
  122.     signed_value +=  sym_value + reloc_entry->addend;
  123.     if ((signed_value&~0x3ffff) == 0) 
  124.     {                /* Absolute jmp/call */
  125.       insn |= (1<<24);        /* Make it absolute */
  126.       /* FIXME: Should we change r_type to R_IABS */
  127.     } 
  128.     else 
  129.     {
  130.       /* Relative jmp/call, so subtract from the value the
  131.      address of the place we're coming from */
  132.       signed_value -= reloc_entry->address + 
  133.        input_section->output_section->vma + 
  134.     input_section->output_offset;
  135.       if (signed_value>0x1ffff || signed_value<-0x20000) 
  136.        return(bfd_reloc_outofrange);
  137.     }
  138.     signed_value >>= 2;
  139.     insn = INSERT_HWORD(insn, signed_value);
  140.     bfd_put_32(abfd, insn ,hit_data); 
  141.     break;
  142.    case R_ILOHALF: 
  143.     insn = bfd_get_32(abfd, hit_data); 
  144.     unsigned_value = EXTRACT_HWORD(insn);
  145.     unsigned_value +=  sym_value + reloc_entry->addend;
  146.     insn = INSERT_HWORD(insn, unsigned_value);
  147.     bfd_put_32(abfd, insn, hit_data); 
  148.     break;
  149.    case R_IHIHALF:
  150.     insn = bfd_get_32(abfd, hit_data); 
  151.     /* consth, part 1 
  152.        Just get the symbol value that is referenced */
  153.     part1_consth_active = true;
  154.     part1_consth_value = sym_value + reloc_entry->addend;
  155.     /* Don't modify insn until R_IHCONST */
  156.     break;
  157.    case R_IHCONST:    
  158.     insn = bfd_get_32(abfd, hit_data); 
  159.     /* consth, part 2 
  160.        Now relocate the reference */
  161.     if (part1_consth_active == false) {
  162.       fprintf(stderr,"Relocation problem : ");
  163.       fprintf(stderr,"IHIHALF missing in module %s\n",
  164.           abfd->filename); 
  165.       return(bfd_reloc_dangerous);
  166.     }
  167.     /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
  168.     unsigned_value = 0;        /*EXTRACT_HWORD(insn) << 16;*/
  169.     unsigned_value += reloc_entry->addend; /* r_symndx */
  170.     unsigned_value += part1_consth_value;
  171.     unsigned_value = unsigned_value >> 16;
  172.     insn = INSERT_HWORD(insn, unsigned_value);
  173.     part1_consth_active = false;
  174.     bfd_put_32(abfd, insn, hit_data); 
  175.     break;
  176.    case R_BYTE:
  177.     insn = bfd_get_8(abfd, hit_data); 
  178.     unsigned_value = insn + sym_value + reloc_entry->addend;    
  179.     if (unsigned_value & 0xffffff00) {
  180.       fprintf(stderr,"Relocation problem : ");
  181.       fprintf(stderr,"byte value too large in module %s\n",
  182.           abfd->filename); 
  183.       return(bfd_reloc_overflow);
  184.     }
  185.     bfd_put_8(abfd, unsigned_value, hit_data); 
  186.     break;
  187.    case R_HWORD:
  188.     insn = bfd_get_16(abfd, hit_data); 
  189.     unsigned_value = insn + sym_value + reloc_entry->addend;    
  190.     if (unsigned_value & 0xffff0000) {
  191.       fprintf(stderr,"Relocation problem : ");
  192.       fprintf(stderr,"hword value too large in module %s\n",
  193.           abfd->filename); 
  194.       return(bfd_reloc_overflow);
  195.     }
  196.  
  197.     bfd_put_16(abfd, insn, hit_data); 
  198.     break;
  199.    case R_WORD:
  200.     insn = bfd_get_32(abfd, hit_data); 
  201.     insn += sym_value + reloc_entry->addend;  
  202.     bfd_put_32(abfd, insn, hit_data);
  203.     break;
  204.    default:
  205.     fprintf(stderr,"Relocation problem : ");
  206.     fprintf(stderr,"Unrecognized reloc type %d, in module %s\n",
  207.         r_type,abfd->filename); 
  208.     return (bfd_reloc_dangerous);
  209.   }
  210.  
  211.  
  212.   return(bfd_reloc_ok);    
  213. }
  214.  
  215. /*      type       rightshift
  216.                size
  217.               bitsize
  218.                    pc-relative
  219.                      bitpos
  220.                      absolute
  221.                          complain_on_overflow
  222.                           special_function
  223.                             relocation name
  224.                                    partial_inplace 
  225.                                       src_mask
  226. */
  227.  
  228. /*FIXME: I'm not real sure about this table */
  229. #define NA    0    /* Obsolete fields, via the documentation */
  230. #define NAB false
  231. static reloc_howto_type howto_table[] = 
  232. {
  233.   {R_ABS,     0, 3, NA, false, NA, NAB, true,a29k_reloc,"ABS",     true, 0xffffffff,0xffffffff, false},
  234.   {1},  {2},  {3},   {4},  {5},  {6},  {7},  {8},  {9}, {10},
  235.   {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20},
  236.   {21}, {22}, {23},
  237.   {R_IREL,    0, 3, NA, true,  NA, NAB, true,a29k_reloc,"IREL",    true, 0xffffffff,0xffffffff, false},
  238.   {R_IABS,    0, 3, NA, false, NA, NAB, true,a29k_reloc,"IABS",    true, 0xffffffff,0xffffffff, false},
  239.   {R_ILOHALF, 0, 3, NA, true,  NA, NAB, true,a29k_reloc,"ILOHALF", true, 0x0000ffff,0x0000ffff, false},
  240.   {R_IHIHALF, 0, 3, NA, true,  NA, NAB, true,a29k_reloc,"IHIHALF", true, 0xffff0000,0xffff0000, false},
  241.   {R_IHCONST, 0, 3, NA, true,  NA, NAB, true,a29k_reloc,"IHCONST", true, 0xffff0000,0xffff0000, false},
  242.   {R_BYTE,    0, 0, NA, false, NA, NAB, true,a29k_reloc,"BYTE",    true, 0x000000ff,0x000000ff, false},
  243.   {R_HWORD,   0, 1, NA, false, NA, NAB, true,a29k_reloc,"HWORD",   true, 0x0000ffff,0x0000ffff, false},
  244.   {R_WORD,    0, 2, NA, false, NA, NAB, true,a29k_reloc,"WORD",    true, 0xffffffff,0xffffffff, false},
  245. };
  246. #undef NA
  247.  
  248. #define BADMAG(x) A29KBADMAG(x)
  249.  
  250. #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
  251.  reloc_processing(relent, reloc, symbols, abfd, section)
  252.  
  253. static void DEFUN(reloc_processing,(relent,reloc, symbols, abfd, section) ,
  254.        arelent *relent AND
  255.        struct internal_reloc *reloc AND
  256.        asymbol **symbols AND
  257.        bfd *abfd AND
  258.        asection *section)
  259. {
  260.     relent->address = reloc->r_vaddr;        
  261.     relent->howto = howto_table + reloc->r_type;
  262.     if (reloc->r_type == R_IHCONST) 
  263.     {        
  264.     relent->addend = reloc->r_symndx;        
  265.     relent->sym_ptr_ptr= bfd_abs_section.symbol_ptr_ptr;
  266.     }
  267.     else 
  268.     {
  269.       asymbol *ptr;
  270.       relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx];
  271.  
  272.       ptr = *(relent->sym_ptr_ptr);
  273.  
  274.       if (ptr 
  275.       && bfd_asymbol_bfd(ptr) == abfd        
  276.  
  277.       && ((ptr->flags & BSF_OLD_COMMON)== 0))    
  278.       {                        
  279.       relent->addend = 0;
  280.       }                        
  281.       else
  282.       {                    
  283.       relent->addend = 0;            
  284.       }            
  285.       relent->address-= section->vma;
  286.   }
  287. }
  288.  
  289. #include "coffcode.h"
  290.  
  291. bfd_target a29kcoff_big_vec =
  292. {
  293.   "coff-a29k-big",        /* name */
  294.   bfd_target_coff_flavour,
  295.   true,                /* data byte order is big */
  296.   true,                /* header byte order is big */
  297.  
  298.   (HAS_RELOC | EXEC_P |        /* object flags */
  299.    HAS_LINENO | HAS_DEBUG |
  300.    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
  301.  
  302.   (SEC_HAS_CONTENTS | SEC_ALLOC /* section flags */
  303.    | SEC_LOAD | SEC_RELOC  
  304.    | SEC_READONLY ),
  305.   '_',                /* leading underscore */
  306.   '/',                /* ar_pad_char */
  307.   15,                /* ar_max_namelen */
  308.   2,                /* minimum section alignment */
  309.   /* data */
  310.   _do_getb64, _do_getb_signed_64, _do_putb64,
  311.      _do_getb32, _do_getb_signed_32,   _do_putb32,
  312.      _do_getb16, _do_getb_signed_16, _do_putb16,
  313.   /* hdrs */
  314.   _do_getb64, _do_getb_signed_64, _do_putb64,
  315.      _do_getb32, _do_getb_signed_32,   _do_putb32,
  316.      _do_getb16, _do_getb_signed_16, _do_putb16,
  317.  
  318.  {
  319.         
  320.    _bfd_dummy_target,
  321.    coff_object_p,
  322.    bfd_generic_archive_p,
  323.    _bfd_dummy_target
  324.   },
  325.  {
  326.    bfd_false,
  327.    coff_mkobject,
  328.    _bfd_generic_mkarchive,
  329.    bfd_false
  330.   },
  331.  {
  332.    bfd_false,
  333.    coff_write_object_contents,
  334.    _bfd_write_archive_contents,
  335.    bfd_false
  336.   },
  337.  
  338.   JUMP_TABLE(coff),
  339.   COFF_SWAP_TABLE
  340.  };
  341.